package com.smmisia.shop.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smmisia.common.Result.Result;
import com.smmisia.shop.api.AttractionService;
import com.smmisia.shop.entity.Business;
import com.smmisia.shop.entity.convetor.BusinessConvertor;
import com.smmisia.shop.enums.BusinessEnum;
import com.smmisia.shop.exception.BusinessErrorCode;
import com.smmisia.shop.exception.ProductException;
import com.smmisia.shop.request.BusinessRegisterRequest;
import com.smmisia.shop.request.BusinessUpdateRequest;
import com.smmisia.shop.response.BusinessInfoResponse;
import com.smmisia.shop.service.BusinessService;
import com.smmisia.shop.mapper.BusinessMapper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;


@Service
@Slf4j
public class BusinessServiceImpl extends ServiceImpl<BusinessMapper, Business>
        implements BusinessService {

    @Autowired
    private BusinessMapper businessMapper;

    @Autowired
    private AttractionService attractionService;

    @Override
    public Result<Boolean> register(BusinessRegisterRequest request) {
        Optional.ofNullable(businessMapper.selectOne(
                        Wrappers.lambdaQuery(Business.class)
                                .eq(Business::getUserId, StpUtil.getLoginIdAsInt())))
                .orElseThrow(() -> new ProductException(BusinessErrorCode.BUSINESS_EXISTED));
        Assert.isTrue(save(Business.create(request)),
                () -> new ProductException(BusinessErrorCode.BUSINESS_SAVA_FAILED));
        //添加到对应景点
        Boolean success = attractionService.insertAttraction(request.getAttractionId(), StpUtil.getLoginIdAsInt()).getSuccess();
        Assert.isTrue(success, () -> new ProductException(BusinessErrorCode.BUSINESS_SAVA_FAILED));
        return Result.ok(true);
    }

    @Override
    public Result<Boolean> updateBusiness(BusinessUpdateRequest request) {
        Business business = businessMapper.selectOne(
                Wrappers.lambdaQuery(Business.class)
                        .eq(Business::getUserId, StpUtil.getLoginIdAsInt()));
        Optional.ofNullable(business)
                .orElseThrow(() -> new ProductException(BusinessErrorCode.BUSINESS_NOT_EXISTED));
        Assert.isTrue(updateById(Business.builder()
                .id(business.getId())
                .description(request.getDescription())
                .images(request.getImages())
                .position(request.getPosition())
                .phone(request.getPhone())
                .tag(request.getTag())
                .startTime(request.getStartTime())
                .endTime(request.getEndTime())
                .build()), () -> new ProductException(BusinessErrorCode.BUSINESS_UPDATE_FAILED));
        return Result.ok(true);
    }

    @Override
    public Result<Boolean> updateStatus(Integer status) {
        Business business = businessMapper.selectOne(
                Wrappers.lambdaQuery(Business.class)
                        .eq(Business::getUserId, StpUtil.getLoginIdAsInt()));
        Optional.ofNullable(business)
                .orElseThrow(() -> new ProductException(BusinessErrorCode.BUSINESS_NOT_EXISTED));
        BusinessEnum newStatus = (business.getStatus() == BusinessEnum.NORMAL) ? BusinessEnum.REST : BusinessEnum.NORMAL;
        Assert.isTrue(updateById(Business.builder()
                .id(business.getId())
                .status(newStatus)
                .build()), () -> new ProductException(BusinessErrorCode.BUSINESS_UPDATE_FAILED));
        return Result.ok(true);
    }

    @Override
    public Result<Boolean> delete() {
        Business business = businessMapper.selectOne(
                Wrappers.lambdaQuery(Business.class)
                        .eq(Business::getUserId, StpUtil.getLoginIdAsInt()));
        Optional.ofNullable(business)
                .orElseThrow(() -> new ProductException(BusinessErrorCode.BUSINESS_NOT_EXISTED));
        Assert.isTrue(removeById(business.getId()), () -> new ProductException(BusinessErrorCode.BUSINESS_DELETE_FAILED));
        return Result.ok(true);
    }

    @Override
    public Result<BusinessInfoResponse> info(Integer id) {
        id = (id == null) ? StpUtil.getLoginIdAsInt() : id;
        Business business = businessMapper.selectById(id);
        Assert.notNull(business, () -> new ProductException(BusinessErrorCode.BUSINESS_NOT_EXISTED));
        return Result.ok(BusinessConvertor.INSTANCE.toBusinessInfo(business));
    }

    @XxlJob(value = "businessPause")
    public void pause() {
        LocalDateTime now = LocalDateTime.now();
        List<Business> businessList = businessMapper.selectList(Wrappers.lambdaQuery(Business.class)
                .eq(Business::getStatus, BusinessEnum.NORMAL));
        businessList.forEach(business -> {
            if (business.getEndTime().isBefore(now)) {
                updateById(Business.builder()
                        .id(business.getId())
                        .status(BusinessEnum.REST)
                        .build());
            }
        });
    }

    @XxlJob(value = "businessStart")
    public void start() {
        LocalDateTime now = LocalDateTime.now();
        List<Business> businessList = businessMapper.selectList(Wrappers.lambdaQuery(Business.class)
                .eq(Business::getStatus, BusinessEnum.REST));
        businessList.forEach(business -> {
            if (business.getStartTime().isBefore(now)) {
                updateById(Business.builder()
                        .id(business.getId())
                        .status(BusinessEnum.NORMAL)
                        .build());
            }
        });
    }
}




